/**
 * Copyright (c) 2009 Netflix-Flex_API Contributors.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy of 
 * this software and associated documentation files (the "Software"), to deal in 
 * the Software without restriction, including without limitation the rights to 
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 
 * of the Software, and to permit persons to whom the Software is furnished to do 
 * so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all 
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE. 
 * */
package com.netflix.webapis.catalog
{
	import com.netflix.webapis.ParamsBase;
	import com.netflix.webapis.ServiceBase;
	import com.netflix.webapis.ServiceFault;
	import com.netflix.webapis.catalog.vo.CategoryItemVO;
	import com.netflix.webapis.events.NetflixFaultEvent;
	import com.netflix.webapis.events.NetflixResultEvent;
	import com.netflix.webapis.xml.NetflixXMLUtil;
	
	import flash.events.IEventDispatcher;
	
	import mx.rpc.AsyncToken;
	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;
	import mx.rpc.http.HTTPService;
	
	import org.iotashan.oauth.OAuthRequest;

	/**
	 * Categories Service to retrieve category information. 
	 * @author jonbcampos
	 * 
	 */	
	public class CategoriesService extends ServiceBase
	{
		public function CategoriesService(target:IEventDispatcher=null)
		{
			super(target);
		}
		
		//----------------------------
		//
		// Public Static Consts
		//
		//----------------------------
		public static const GENRES_SERVICE:String = "genres";
		public static const TV_RATINGS_SERVICE:String = "tvRatings";
		public static const MPAA_RATINGS_SERVICE:String = "mpaaRatings";
		public static const QUEUE_AVAILABILITY_SERVICE:String = "queueAvailability";
		public static const TITLE_FORMATS_SERVICE:String = "titleFormats";
		
		//----------------------------
		//
		// Protected Static Consts
		//
		//----------------------------
		protected static const GENRES_URL:String = NETFLIX_BASE_URL+"categories/genres";
		protected static const TV_RATINGS_URL:String = NETFLIX_BASE_URL+"categories/tv_ratings";
		protected static const MPAA_RATINGS_URL:String = NETFLIX_BASE_URL+"categories/mpaa_ratings";
		protected static const QUEUE_AVAILABILITY_URL:String = NETFLIX_BASE_URL+"categories/queue_availability";
		protected static const TITLE_FORMATS_URL:String = NETFLIX_BASE_URL+"categories/title_formats";
		
		//----------------------------
		//
		// Public Variables
		//
		//----------------------------
		[Bindable]
		[Inspectable(enumeration="genres,tvRatings,mpaaRatings,queueAvailability,titleFormats",defaultValue="genres")]
		public var type:String = GENRES_SERVICE;
		
		//----------------------------
		//
		// Private Variables
		//
		//----------------------------
		private var _service:HTTPService;
		
		//----------------------------
		//
		// Public Methods
		//
		//----------------------------
		/**
		 * @inherit
		 */
		override public function send(parameters:ParamsBase=null):void
		{
			super.send(parameters);
			
			switch(type)
			{
				case GENRES_SERVICE:
					genresService(parameters);
				break;
				case TV_RATINGS_SERVICE:
					tvRatingsService(parameters);
				break;
				case MPAA_RATINGS_SERVICE:
					mpaaRatingsService(parameters);
				break;
				case QUEUE_AVAILABILITY_SERVICE:
					queueAvailabilityService(parameters);
				break;
				case TITLE_FORMATS_SERVICE:
					titleFormatsService(parameters);
				break;
			}
		}
		/**
		 * Calls for the genresService Service. 
		 * @param params
		 * 
		 */	
		public function genresService(params:ParamsBase=null):void
		{
			handleServiceLoading(GENRES_URL,NetflixResultEvent.GENRES_RESULT,determineParams(params,GENRES_SERVICE));
		}
		/**
		 * Calls for the tvRatingsService Service. 
		 * @param params
		 * 
		 */	
		public function tvRatingsService(params:ParamsBase=null):void
		{
			handleServiceLoading(TV_RATINGS_URL,NetflixResultEvent.TV_RATINGS_RESULT,determineParams(params,TV_RATINGS_SERVICE));
		}
		/**
		 * Calls for the mpaaRatingsService Service. 
		 * @param params
		 * 
		 */	
		public function mpaaRatingsService(params:ParamsBase=null):void
		{
			handleServiceLoading(MPAA_RATINGS_URL,NetflixResultEvent.MPAA_RATINGS_RESULT,determineParams(params,MPAA_RATINGS_SERVICE));
		}
		/**
		 * Calls for the queueAvailabilityService Service. 
		 * @param params
		 * 
		 */	
		public function queueAvailabilityService(params:ParamsBase=null):void
		{
			handleServiceLoading(QUEUE_AVAILABILITY_URL,NetflixResultEvent.QUEUE_AVAILABILITY_RESULT,determineParams(params,QUEUE_AVAILABILITY_SERVICE));
		}
		/**
		 * Calls for the titleFormatsService Service. 
		 * @param params
		 * 
		 */	
		public function titleFormatsService(params:ParamsBase=null):void
		{
			handleServiceLoading(TITLE_FORMATS_URL,NetflixResultEvent.TITLE_FORMATS_RESULT,determineParams(params,TITLE_FORMATS_SERVICE));
		}
		
		/**
		 * @inherit
		 */	
		override protected function handleServiceLoading(methodString:String, dispatchType:String, params:ParamsBase = null):void
		{
			super.handleServiceLoading(methodString,dispatchType, params);
			
			var sendQuery:String = methodString;
			var typeQuery:String;
			
			_service = new HTTPService();
			var tokenRequest:OAuthRequest = new OAuthRequest("GET",sendQuery,params.toObject(),consumer,accessToken);
			_service.url = tokenRequest.buildRequest(SIG_METHOD);
			trace(tokenRequest.buildRequest(SIG_METHOD));
			_service.method = "GET";
			_service.resultFormat = "e4x";
			_service.addEventListener(ResultEvent.RESULT,onCompleteHandler);
			_service.addEventListener(FaultEvent.FAULT,onFault);
			_service.send();
		
			function onCompleteHandler(event:ResultEvent):void
			{
				_service.removeEventListener(ResultEvent.RESULT,onCompleteHandler);
				_service.removeEventListener(FaultEvent.FAULT,onFault);
				var queryXML:XML = event.result as XML;
				
				if(queryXML.Error == undefined)
					formatAndDispatch(queryXML, dispatchType);
				else
					dispatchFault(new ServiceFault(NetflixFaultEvent.API_RESPONSE, queryXML.Error, queryXML.Error.Message));
			}
			
			function onFault(event:FaultEvent):void
			{
				_service.removeEventListener(ResultEvent.RESULT,onCompleteHandler);
				_service.removeEventListener(FaultEvent.FAULT,onFault);
				dispatchFault(new ServiceFault(event.fault.faultCode,event.fault.faultString,event.fault.faultDetail));
			}
		}
		
		/**
		 * @inherit
		 */		
		override protected function formatAndDispatch(returnedXML:XML, dispatchType:String):void
		{
			super.formatAndDispatch(returnedXML,dispatchType);
			
			var resultsArray:Array = new Array();
			var resultNode:XML;
			
			//loop through child nodes and build value objects based on catagory type
			switch(dispatchType)
			{
				case NetflixResultEvent.GENRES_RESULT:
				case NetflixResultEvent.MPAA_RATINGS_RESULT:
				case NetflixResultEvent.TV_RATINGS_RESULT:
				case NetflixResultEvent.TITLE_FORMATS_RESULT:
				case NetflixResultEvent.QUEUE_AVAILABILITY_RESULT:
					for each(resultNode in returnedXML..category_item){
						var categoryItem:CategoryItemVO = NetflixXMLUtil.handleCategory(resultNode);
						resultsArray.push(categoryItem);
					}
				break;
			}
			if(resultsArray==null || resultsArray.length==0){
				dispatchFault(new ServiceFault(NetflixFaultEvent.API_RESPONSE, "Parameter Errors", "No valid 'expand' option was selected."));
				return;
			}
			dispatchResult(resultsArray,dispatchType);
		}
		
	}
}